﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Eco.ObjectImplementation;
using Eco.ObjectRepresentation;
using Eco.Services;

namespace Eco.Persistence
{
	public static class EcoSqlHelper
	{
		public static IEcoList<T> ExecuteSql<T>(IEcoServiceProvider serviceProvider, string sql, IEnumerable<object> parameterValues) where T : class, IEcoObject
		{
			return ExecuteSql<T>(serviceProvider, sql, parameterValues, 0, -1);
		}

		public static IEcoList<T> ExecuteSql<T>(IEcoServiceProvider serviceProvider, string sql, IEnumerable<object> parameterValues, int startRecord, int maxRecords) where T : class, IEcoObject
		{
			var sqlService = serviceProvider.GetEcoService<ISqlPsService>();
			var vfs = serviceProvider.GetEcoService<IVariableFactoryService>();
			var vars = vfs.CreateVariableList();
			if (parameterValues != null)
				AddSqlParameterValues(parameterValues, vars);
			return sqlService.Execute(typeof(T), PreparseSql(sql), vars, maxRecords, startRecord).GetAsEcoList<T>();
		}

		public static string PreparseSql(string sql)
		{
			var sb = new StringBuilder();
			int par = 0;
			foreach (var c in sql)
			{
				if (c == '?')
					sb.Append(string.Format(":p{0}", par++));
				else
					sb.Append(c);
			}
			return sb.ToString();
		}

		public static void AddSqlParameterValues(IEnumerable<object> parameterValues, IModifiableVariableList vars)
		{
			var pv = parameterValues.ToList();
			for (int i = 0; i < pv.Count; i++)
			{
				var v = pv[i];
				var name = string.Format("p{0}", i);
				if (v is IEcoObject)
					vars.Add(name, ((IEcoObject)v).AsIObject());
				else if (v is IElement)
					vars.Add(name, (IElement)v);
				else if (v is Type)
					vars.AddConstant(name, ((Type)v).AssemblyQualifiedName);
				else
					vars.AddConstant(name, v);
			}
		}
	}
}
